package com.zed.app.push.util;

import java.io.IOException;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;


import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.http.HttpEntity;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.HttpClientConnectionManager;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.client.LaxRedirectStrategy;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.util.EntityUtils;

import com.zed.app.push.SystemConfig;

public class HttpClient {
	/**
	 * 日志处理类
	 */
	private static final Log log = LogFactory.getLog(HttpClient.class);

	// 读取超时
	private final static int SOCKET_TIMEOUT = SystemConfig.getInt("request.socket.timeout");
	// 连接超时
	private final static int CONNECTION_TIMEOUT = SystemConfig.getInt("request.connection.timeout");
	// 每个HOST的最大连接数量
	private final static int MAX_CONN_PRE_HOST = SystemConfig.getInt("request.max.conn.pre.host");
	// 连接池的最大连接数
	private final static int MAX_CONN = SystemConfig.getInt("request.max.conn");
	// 连接池
	private static PoolingHttpClientConnectionManager httpConnectionManager;

	private static final HttpClient httpClient = new HttpClient();

	public static HttpClient getInstance() {
		initClient();
		return httpClient;
	}


	private static void initClient() {
			httpConnectionManager = new PoolingHttpClientConnectionManager();
			httpConnectionManager.setMaxTotal(MAX_CONN);
			// 设置单个路由最大连接数量
			httpConnectionManager.setDefaultMaxPerRoute(MAX_CONN_PRE_HOST);
			new IdleConnectionMonitorThread(httpConnectionManager).start();
	}

	/**
	 * 发送主要方法,异常捕获
	 * 
	 * @param post
	 * @param code
	 * @return
	 * @throws Exception
	 */
	public Map<String, String> doHttpRequest(String url, Map<String, String> headers, String data) throws Exception {
		Map<String, String> result = new HashMap<String, String>();

		HttpPost httpPost = new HttpPost(url);
		httpPost.setEntity(new StringEntity(data, "UTF-8"));
		for (java.util.Map.Entry<String, String> head : headers.entrySet()) {
			httpPost.addHeader(head.getKey(), head.getValue());
		}
		CloseableHttpResponse httpResponse = null;
		try {
			httpResponse = getHttpClient().execute(httpPost);
			// 添加请求状态码
			result.put("code", String.valueOf(httpResponse.getStatusLine().getStatusCode()));

			if (httpResponse.getStatusLine().getStatusCode() == 200) {
				HttpEntity entity = httpResponse.getEntity();
				if (null != entity) {
					String requestResult = EntityUtils.toString(entity, "UTF-8");
					// 添加请求返回结果
					result.put("result", requestResult);
				}
				EntityUtils.consume(entity);
			}
		} finally {
			try {
				if (httpResponse != null)
					httpResponse.close();
			} catch (IOException e) {
				log.error("", e);
			}
		}
		return result;
	}

	/**
	 * 
	 * 方法名：getHttpClient 作者：zhouyh 创建时间：2016-2-18 下午01:23:32
	 * 描述：多线程调用时，需要创建自己的httpclient
	 * 
	 * @return
	 * @throws KeyStoreException
	 * @throws IOException
	 * @throws CertificateException
	 * @throws NoSuchAlgorithmException
	 * @throws UnrecoverableKeyException
	 * @throws KeyManagementException
	 */
	public static CloseableHttpClient getHttpClient() throws KeyStoreException, NoSuchAlgorithmException,
			CertificateException, IOException, KeyManagementException, UnrecoverableKeyException {
		// 创建全局的requestConfig
		RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(CONNECTION_TIMEOUT)
				.setSocketTimeout(SOCKET_TIMEOUT).build();
		// 声明重定向策略对象
		LaxRedirectStrategy redirectStrategy = new LaxRedirectStrategy();

		CloseableHttpClient httpClient = HttpClients.custom().setConnectionManager(httpConnectionManager)
				.setDefaultRequestConfig(requestConfig).setRedirectStrategy(redirectStrategy).build();
		return httpClient;
	}

	public static class IdleConnectionMonitorThread extends Thread {

		private final HttpClientConnectionManager connMgr;
		private volatile boolean shutdown;

		public IdleConnectionMonitorThread(HttpClientConnectionManager connMgr) {
			super();
			this.connMgr = connMgr;
		}

		@Override
		public void run() {
			try {
				while (!shutdown) {
					synchronized (this) {
						wait(5000);
						// 关闭失效的连接
						connMgr.closeExpiredConnections();
						// 可选的, 关闭30秒内不活动的连接
						connMgr.closeIdleConnections(30, TimeUnit.SECONDS);
					}
				}
			} catch (InterruptedException ex) {
				log.error("", ex);
				// terminate
			}
		}

		public void shutdown() {
			shutdown = true;
			synchronized (this) {
				notifyAll();
			}
		}

	}
}
